package com.intelligent.system.auth.uitls;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.intelligent.system.auth.entity.UserToken;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.security.PublicKey;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * Token工具类
 * 用于生成、解析和验证token
 */
@Slf4j
@Component
public class TokenUtils {

    @Value("${jwt.secret:your-secret-key}")
    private String secret;

    @Value("${jwt.expiration:86400}")
    private Long expiration;

    @Autowired
    private OAuth2CertUtils oauth2CertUtils;

    private final ObjectMapper objectMapper = new ObjectMapper();
    private byte[] secretKey;

    @PostConstruct
    public void init() {
        this.secretKey = secret.getBytes();
    }

    /**
     * 从Authorization头中提取token
     * 支持 "Bearer token" 和直接token两种格式
     */
    public String extractToken(String authorization) {
        if (authorization == null || authorization.trim().isEmpty()) {
            return null;
        }

        if (authorization.startsWith("Bearer ")) {
            return authorization.substring(7);
        }

        return authorization;
    }

    /**
     * 解析token
     * 使用OAuth2服务器的公钥验证token
     */
    public Claims parseToken(String token) {
        try {
            PublicKey publicKey = oauth2CertUtils.getPublicKey();
            return Jwts.parser()
                    .setSigningKey(publicKey)
                    .parseClaimsJws(token)
                    .getBody();
        } catch (Exception e) {
            log.error("解析token时发生错误: {}", e.getMessage());
            return null;
        }
    }

    /**
     * 验证token是否有效
     */
    public boolean validateToken(String token) {
        try {
            Claims claims = parseToken(token);
            if (claims == null) {
                return false;
            }

            // 检查token是否过期
            Date expiration = claims.getExpiration();
            return !expiration.before(new Date());
        } catch (Exception e) {
            log.error("验证token时发生错误: {}", e.getMessage());
            return false;
        }
    }

    /**
     * 从token中获取用户信息
     */
    public UserToken getUserInfoFromToken(String token) {
        try {
            Claims claims = parseToken(token);
            if (claims == null) {
                return null;
            }

            // 从claims中提取用户信息
            UserToken userToken = new UserToken();
            userToken.setUserId(claims.get("userId", Long.class));
            userToken.setUserName(claims.get("userName", String.class));
            userToken.setYkzAccountId(claims.get("ykzAccountId", Long.class));
            userToken.setOrgId(claims.get("orgId", String.class));
            userToken.setCreateTime(claims.get("createTime", Long.class));
            userToken.setEndTime(claims.get("endTime", Long.class));

            return userToken;
        } catch (Exception e) {
            log.error("从token中获取用户信息时发生错误: {}", e.getMessage());
            return null;
        }
    }

    /**
     * 生成token
     * 注意：此方法仅用于测试，实际token应由OAuth2服务器生成
     */
    public String generateToken(UserToken userToken) {
        try {
            Date now = new Date();
            Date expiryDate = new Date(now.getTime() + expiration * 1000);

            Map<String, Object> claims = new HashMap<>();
            claims.put("userId", userToken.getUserId());
            claims.put("userName", userToken.getUserName());
            claims.put("ykzAccountId", userToken.getYkzAccountId());
            claims.put("orgId", userToken.getOrgId());
            claims.put("createTime", userToken.getCreateTime());
            claims.put("endTime", userToken.getEndTime());

            return Jwts.builder()
                    .setClaims(claims)
                    .setIssuedAt(now)
                    .setExpiration(expiryDate)
                    .signWith(SignatureAlgorithm.HS512, secretKey)
                    .compact();
        } catch (Exception e) {
            log.error("生成token时发生错误: {}", e.getMessage());
            return null;
        }
    }
} 